home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Development Tools & Languages / Macintosh Common Lisp Related / User Contributions / Misc.sea / Misc / print-u.lisp-0 / print-u.lisp-0
Encoding:
Text File  |  1993-02-26  |  70.2 KB  |  1,792 lines  |  [TEXT/CCL2]

  1. (in-package :ccl)
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;; print-u.lisp
  4. ;;
  5. ;; Copyright  1992,1993 University of Toronto, Department of Computer Science
  6. ;; All Rights Reserved
  7. ;;
  8. ;; author: Mark A. Tapia markt@dgp.toronto.edu or markt@dgp.utoronto.ca
  9. ;;
  10. ;; print-u is a package for printing windows and documents. 
  11. ;; The following methods and functions are exported:
  12. ;;        get-printer-error    for returning the error condition or nil (no error)
  13. ;;        page-size            point indicating the page size used for printing
  14. ;;        picture-hardcopy     for quickdraw pictures
  15. ;;        print-contents       for drawing the nested views of a window
  16. ;;        view-print-contents  for printing a series of views
  17. ;;        scale-line-width     sets the scaling factor for line width for PostScript devices
  18. ;;        normal-line-width    sets PostScript line width to (1 1)
  19. ;;
  20. ;; Internal (unexported) routines of interest
  21. ;;        document-hardcopy    for printing a general document
  22. ;;        window-hardcopy      for printing the contents of a window using
  23. ;;                             print-contents
  24.  
  25. ;;                             Routines that handle public and private print records
  26. ;;        check-print-prec     retrieves and validates the print record (get-print-prec object)
  27. ;;        default-prec         creates a default private print record
  28. ;;        get-prec             retrieves (and possibly creates) a print record for an object
  29. ;;        get-print-prec       calls get-prec on the outermost containing view
  30. ;;        prec-get             retrieves a print record for an object
  31. ;;        prec-put             associates a print-record with an object
  32. ;;        remove-prec          removes a print-record associated with an object
  33. ;;        remove-hc-prec       removes the public print-record
  34. ;;        replace-prec         replaces the print record associated with the object
  35. ;;                             only if it is different
  36. ;;        update-file-prec     saves a copy of a private print record in a resource 
  37. ;;        view-file-name       the pathname of the file associated with an object
  38. ;;
  39. ;; Acknowledgements:
  40. ;;     This code is based on print-utils.lisp written by DEH 6/20/91 and
  41. ;;     based on hardcopy.lisp with copyright 1988-89 Apple Computer, Inc. 
  42. ;;     The print-utils code has been modified to work in MCL2.0 and
  43. ;;     to print the contents of other views and to support generalized printing.
  44. ;;
  45. ;;     This code also uses the with-view-font and with-pen-state macros
  46. ;;     from oodles-of-utils:quickdraw-u.lisp by Michael S. Engber.
  47. ;;     Copyright  1991 Northwestern University Institute for the Learning Sciences
  48. ;;     All Rights Reserved.
  49. ;;
  50. ;;     Support for private print records was based on suggestions by Gregory
  51. ;;     Wilcox. The ideas were refined by Bill St. Clair.
  52. ;;
  53. ;;     Support for the setLineWidth PostScript command based on suggestions
  54. ;;     by Kemi Jona.
  55. ;;
  56. ;; Update history:
  57. ;;  1992-06-07  Added page-size method for retrieving the page size
  58. ;;  1992-10-27  Addeed support for private print records stored with the
  59. ;;              file in the resource fork (:type :prec :resource-id 128).
  60. ;;  1993-02-08  Added support for setLineWidth for PostScript lines.
  61. ;;              Replaced (require :QuickDraw) with macro with-rectangle-arg 
  62. ;;              and function setup-rect, if not present.
  63. ;;
  64. ;; NOTE: Every window has a private print record which controls the
  65. ;;       way the window will be printed and the attributes in the
  66. ;;       print-style-dialog box. The private print record is stored in the
  67. ;;       resource fork of the file when it is saved (:type :prec :resource-d 128)
  68. ;;       and when the Page Setup method is selected.
  69. ;;       The private print record is restored when the file is edited again.
  70. ;;       
  71. ;;       Every specific view uses the private print record of the outermost
  72. ;;       view containing the specific view.
  73. ;;
  74. ;;       A private print record of a window is saved when the window
  75. ;;       is saved (using Save, Save As, or Save Copy As and when the
  76. ;;       window is closed and needs to be saved. Methods are defined
  77. ;;       for fred windows.
  78. ;;
  79. ;;       For all other windows, you must provide a method for saving
  80. ;;       the file (ccl::window-save using ccl::window-file-save which
  81. ;;       must return the pathname) and a method for (view-file-name window)
  82. ;;        
  83. ;;       When a titled fred-window is saved (using the file menu
  84. ;;       items "save", "Save As ..." "Save Copy As..."), the page 
  85. ;;       setup attributes are saved in a print record in the file. 
  86. ;;       The record is placed in the :prec resource with id 128.  
  87. ;;       When the file is reopened in a fred-window, the page setup 
  88. ;;       attributes are restored.
  89. ;;    
  90. ;;
  91. ;;       Every other object uses a shared, public print record *print-hc-prec*.
  92. ;;       This print record is initialized at the beginning of a session.
  93. ;;
  94. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  95. ;;
  96. ;; Warnings:
  97. ;;     1. If you are running MCL2.0b1p3 or earlier, you must remove
  98. ;;        the semi-colons from before the (pushnew ...) form below.
  99.  
  100. ;;(pushnew :not-mcl-final *features*)
  101.  
  102. ;;
  103. ;;     2. This code will only work if the records definitions in the
  104. ;;        library;interfaces:printTraps.lisp are correct. 
  105. ;;        See the note below.
  106. ;;
  107. ;;     3. The code has been tested with LaserWriters but has not
  108. ;;        been tested with ImageWriters, StyleWriters etc. The routines
  109. ;;        use standard quickdraw calls.
  110. ;;
  111. ;;     4. This code changes the File menu-items for Page Setup and Print.
  112. ;;        The Page Setup menu item is changed to a window-menu-item and
  113. ;;        the associated menu-item action is #'ccl::page-setup. 
  114. ;;        Changing the page setup for a window does not affect
  115. ;;        other windows.
  116. ;;        
  117. ;;     5. Printing can only be cancelled by pressing Command-period.
  118. ;;        Printing cannot be stopped while the current page is being
  119. ;;        printed. but will be stopped before printing the next page.
  120. ;;  
  121. ;;     6. Due to a bug in background printing, we cannot display the
  122. ;;        current page being printed under certain conditions.
  123. ;;        When the print monitor is displaying the status of printing
  124. ;;        (with background printing off), (event-dispatch) does not return.
  125. ;;        As a result, the print progress dialog box does not indicate the
  126. ;;        page number of the page being printed.
  127. ;;
  128. ;;     7. The internal code for printing a document runs without interrupts
  129. ;;        with the result that no other work can proceed until either
  130. ;;        the hardcopy routine returns (or aborts) or is cancelled by
  131. ;;        pressing command-period.
  132. ;;
  133. ;;     8. If you are using oodles-of-utils (the oou: package), and have
  134. ;;        loaded quickdraw-u, print-u redefines the with-pen-state and
  135. ;;        with-font-spec macros
  136. ;;         
  137. ;;
  138. ;;  Six examples of using the package are included at the end of this file:
  139. ;;    four printing examples, for printing various objects:
  140. ;;    - a small window
  141. ;;    - a picture
  142. ;;    - a large window
  143. ;;    - a general document
  144. ;;    and two examples of using private print records
  145. ;;    - creating a file, changing its print record, saving it and restoring it.
  146. ;;    - developing a class of views that store a print record in a slot
  147. ;;
  148. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  149.  
  150. #|
  151. ;;---------------------------Note-------------------------------------
  152.  
  153. ****Warning****
  154. Before loading this file, evaluate
  155.     (record-length :TPrint)
  156. This should return 120.
  157.  
  158. If the record-length is not 120, the tprstl and tprxinfo records 
  159. in the file printTraps.lisp in interfaces folder in the library
  160. folder must be replaced by the following: 
  161.  
  162. (defrecord tprstl
  163.   (wdev :signed-integer)
  164.   (ipagev :signed-integer)
  165.   (ipageh :signed-integer)
  166.   (bport :signed-byte)
  167.   (feed :unsigned-byte))
  168.  
  169. (defrecord tprxinfo
  170.   (irowbytes :signed-integer)
  171.   (ibandv :signed-integer)
  172.   (ibandh :signed-integer)
  173.   (idevbytes :signed-integer)
  174.   (ibands :signed-integer)
  175.   (bpatscale :signed-byte)
  176.   (bulthick :signed-byte)
  177.   (buloffset :signed-byte)
  178.   (bulshadow :signed-byte)
  179.   (scan :unsigned-byte)
  180.   (bxinfox :signed-byte))
  181.  
  182. Perform the following steps to update the record definitions:
  183. 1. Replace the record definitions in the source file
  184.    library;interfaces:printTraps.lisp with the definitions above. 
  185. 2. Evaluate the following expression to rebuild the index files
  186.    (ccl::reindex-interfaces)
  187.    You will now be able to access the new record definitions.
  188. 3. Quit from MCL. To free up the cons space.
  189. 4. Startup MCL again.
  190.  
  191. ----------------------Exported routines------------------------
  192.  
  193. The following exported routines allow the user to change the 
  194. print style for windows. Changing a print style only affects the
  195. current session. The print styles are reset upon re-entering MCL
  196. and are not stored with the document. Changing the style for 
  197. a fred window only changes the style of all fred windows during
  198. the session. Similarly changing the style of a non-fred window 
  199. only changes the styles for all fred windows.
  200.  
  201. page-setup                              ; method
  202. Changes the print style for a window.
  203.  
  204. (page-setup fred-window)
  205. Same as selecting the file Page Setup menu item from the
  206. standard *file-menu*.
  207. Displays the page setup dialog box and allows the user to
  208. change the style attributes for printing the window
  209. but does not affect the style for printing other windows
  210. or documents.
  211.  
  212. (page-setup t)
  213. Displays the page setup dialog box and allows the user to
  214. change the style attributes for all items that do not have
  215. private print records.
  216.  
  217. page-size                              ; method
  218. Returns a point indicating the page size used for printing
  219. fred or non-fred windows. The page-size for a fred window 
  220. may be different from that of a non-fred window.
  221.  
  222. (page-size fred-window)
  223. (page-size t)
  224.  
  225. The following exported routines direct output to a printer or
  226. to a PostScript file.
  227.  
  228. picture-hardcopy                        ; function
  229. picture-hardcopy picture &optional show-dialog?
  230.   Directs the quickdraw picture to the printer
  231.     picture       a picture
  232.     show-dialog?  ignored
  233.  
  234.    If no printer errors occurred and the user did not cancel
  235.       returns nil
  236.    otherwise 
  237.       returns the non-zero print error code which caused the termination
  238.  
  239. print-contents                          ; method
  240. print-contents view &optional (offset #@(0 0))
  241. Executes the quickdraw commands for drawing the contents of a view.
  242.  
  243. When offset is #@(0 0), uses local coordinates for drawing,
  244. otherwise adjusts coordinates by subtracting offset from coordinates.
  245.  
  246. Print-contents supports the following types of views:
  247.     window                    - draws a box around the content area
  248.                                 of the window and prints the contents
  249.                                 of the subviews.
  250.  
  251.     static-text-dialog-item   - draws a box around the item
  252.                                 and prints the text with the view font
  253.  
  254.     editable-text-dialog-item - draws a box around the item
  255.                                 and prints the text with the view font
  256.  
  257.     button-dialog-item        - draws the button and the text within
  258.  
  259.     view                      - prints the contents of the subviews
  260.  
  261.     sv                        - does nothing
  262.  
  263. get-printer-error                       ; function
  264. (get-printer-error)
  265. either returns nil or a printer-condition
  266. If nil, indicates no errors occurred during the last print request.
  267. Otherwise, returns the printer-condition with slots:
  268. phase - either $err-printer??? or nil
  269. code  - either the code returned from the printer operation or nil
  270. cond  - either nil or an error condition when not a printer error
  271.  
  272.  
  273.                                         ; PostScript
  274. -- PostScript routines --
  275. The scale-line-width and normal-line-width routines affect PostScript
  276. devices only. Use these commands in document-hardcopy or to create
  277. a picture printed by picture-hardcopy, when using a PostScript device.
  278.  
  279. For details on set-line-width and picture comments, see Mac Tech Notes #175
  280. (SetLineWidth Revealed) and #91 (Optimizing for the LaserWriter - Picture 
  281. Comments).
  282.  
  283. (scale-line-width scale)                ; function
  284. Sets the scale factor for the Postscript pen width, has no effect
  285. on QuickDraw devices.
  286.  
  287. Scale is the rational used for scaling the Quickdraw pen width
  288. For the thinest lines possible on a LaserWriter at Reduce/Enlarge=100%
  289.   (1) set the quickdraw pen width to #@(1 1)
  290.   (2) call (scale-line-width 1/4)
  291.  
  292. (normal-line-width)                     ; function
  293. Sets the scale factor to 1 for the Postscript pen width, has no effect
  294. on QuickDraw devices.
  295.  
  296.  
  297.  
  298. ----------------------Unexported routines------------------------
  299.  
  300. Window-hardcopy prints the contents of a window.
  301. Specialize if you want to acheive different effects for
  302. other kinds of windows.
  303.  
  304. Use view-print-contents to initiate the printing of a view
  305. and all of its subviews.
  306.  
  307. Use the print-contents methods as the basis for developing
  308. methods for other types of views.
  309.  
  310. Document-hardcopy is a general routine that forms the basis
  311. for other print routines. Call this routine if you want
  312. to develop your own custom printing functions fo documents
  313. and windows.
  314.  
  315. window-hardcopy                         ; method
  316. window-hardcopy (window window) &optional (show-dialog? t)
  317.    Prints the window, The show-dialog? parameter is present
  318.    for compatibility with the standard method for fred-windows
  319.    and is used to display the print job dialog.
  320.    
  321.    The basic routine calls print-contents on the window, which
  322.    repeatedly calls print-contents on the views and subviews.
  323.  
  324.    If no printer errors occurred and the user did not cancel
  325.       returns t
  326.    otherwise 
  327.       returns nil indicating an error occurred in printing
  328.  
  329.     Parameters
  330.       window           the window to be printed
  331.        show-dialog?    display the print job dialog (default t)
  332.  
  333.  
  334. document-hardcopy                       ; not exported
  335. document-hardcopy  print-fn compute-doc-size &key view (show-dialog? t)
  336.    Prints a document. The show-dialog? parameter is present
  337.    for compatibility with the standard method for printing 
  338.    fred-windows and is used to display the print job dialog.
  339.  
  340.    This routine is the basis for picture-hardcopy and window-hardcopy.
  341.    Use document-hardcopy to build other specialized hardcopy routines.
  342.  
  343.    If no printer errors occurred and the user did not cancel
  344.       returns t
  345.    otherwise 
  346.       returns nil indicating an error occurred in printing
  347.  
  348.    The routine performs the following sequence of operations
  349.    1. Opens the printer
  350.    2. Displays the print job dialog box which indicates the method for cancelling.
  351.    3. Retrieves the print record
  352.    4. Determines the page layout using the rectangle corners
  353.       returned by the document-corners function
  354.    5. Opens the printer document
  355.    6. While there are pages to print and the user has not pressed cancel
  356.          For each page in the document that is to be printed, repeats the 
  357.          following steps
  358.             a. opens the page
  359.             b. draws the page using the print-fn
  360.             c. closes the page
  361.    7. Closes the printer document
  362.    8. Closes the printer
  363.    9  If no printer errors occurred and the user did not cancel
  364.          returns t
  365.       otherwise 
  366.          returns nil indicating an error occurred in printing
  367.       Use (get-printer-error) to retrive the printer error condition.
  368.  
  369.     Parameters
  370.     document-corners 
  371.                   Function that computes the corners of the document
  372.                   Parameters:
  373.                        view         the view associated with the document
  374.                        page-size    a point representing the size of the
  375.                                     page-rectangle in pixels
  376.                   Returns the corners of the document rectangle
  377.                   Where the default points are #@(0 0) page-size
  378.                        topleft      the top left corner
  379.                        bottomRight  the bottom right corner
  380.                   If document-corners is not a function, uses the routine
  381.                   default-document-corners which returns the points defining
  382.                   the page rectangle.
  383.  
  384.    print-fn       Function that draws a picture of the document.
  385.                   Parameters:
  386.                        view        suppled by the view keyword. This should be a view
  387.                                    or nil.
  388.                        page-size   the page rectangle size as a point (top left = #@(0 0))
  389.                        page-no     the current page being printed
  390.                        offset      the top left corner of the portion of the document
  391.                   If local, prints the rectangular portion of the document defined 
  392.                      by the points offset (add-points offset page-size). The
  393.                      coordinates are unchanged.
  394.                   Otherwise, adjusts the coordinates by subtracting offset
  395.                      from all points to print within the page rectangle #@(0 0)
  396.                      page-size.
  397.  
  398.                   If print-fn is not a function, uses default-document-hardcopy
  399.                   which does nothing.
  400.  
  401.    :view          the view, default is nil for no view. Passed as a parameter to
  402.                   document-corners and print-fn.
  403.  
  404.    :show-dialog?  display the print job dialog (default t)
  405.  
  406.    :local         default is t. If true, use the document coordinates while printing
  407.                   otherwise use coordinates within the page rectangle,
  408.                   by adjusting all coordinates by offset. 
  409.  
  410. |#
  411.  
  412. (export '(picture-hardcopy print-contents page-setup get-printer-error page-size))
  413. (provide 'print-u)
  414.  
  415. ;; prepare to redefine the functions get-prec and remove-prec by a standard generic function
  416. (progn
  417.   (when (and (fboundp 'get-prec) 
  418.              (equal (type-of #'get-prec) 'function))
  419.     (fmakunbound 'get-prec))
  420.   (when (and (fboundp 'remove-prec)
  421.              (equal (type-of #'get-prec) 'function))
  422.     (fmakunbound 'remove-prec))
  423.   (setq *save-exit-functions*
  424.         (remove 'remove-prec *save-exit-functions* :key #'function-name)))
  425.  
  426. (eval-when (eval load compile)
  427.   (require :resources))
  428.  
  429. #-not-mcl-final 
  430. (eval-when (eval compile) 
  431.   (require :quickDraw))
  432. #+not-mcl-final
  433. (eval-when (eval compile) 
  434.   (ccl::require-interface :printTraps)
  435.                                         ;(require :quickDraw) replaced by two macros below
  436.   (require :loop)                       ; loop is automatically included in MCL 2.0f
  437.   )
  438.  
  439.  
  440. ;; Routines from quickdraw-u.lisp from Michael S. Engber
  441. ;;     Copyright  1991 Northwestern University Institute for the Learning Sciences
  442. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  443.  
  444. ;; the following macros are standard in MCL2.0 final
  445. #+not-mcl-final 
  446. (eval-when (:compile-toplevel :load-toplevel :execute)
  447.   
  448.   (defmacro href (pointer accessor)
  449.     `(rref ,pointer ,accessor :storage :handle))
  450.   
  451.   (defmacro pref (pointer accessor)
  452.     `(rref ,pointer ,accessor :storage :pointer)))
  453.   
  454. (defmacro hset (pointer accessor thing)
  455.   `(rset ,pointer ,accessor ,thing :storage :handle))
  456.  
  457. (defmacro pset (pointer accessor thing)
  458.   `(rset ,pointer ,accessor ,thing :storage :pointer))
  459.  
  460. (unless (fboundp 'with-rectangle-arg)
  461.                                         ; add quickdraw support routines
  462.   (defmacro with-rectangle-arg ((var left &optional top right bottom) &body body)
  463.     "takes a rectangle, two points, or four coordinates and makes a rectangle.
  464. body is evaluated with VAR bound to that rectangle."
  465.     `(rlet ((,var :rect))
  466.        (setup-rect ,var ,left ,top ,right ,bottom)
  467.        ,@body))
  468.  
  469.   (defun setup-rect (rect left top right bottom)
  470.     (cond (bottom
  471.            (setf (pref rect rect.topleft) (make-point left top))
  472.            (setf (pref rect rect.bottomright) (make-point right bottom)))
  473.           (right
  474.            (error "Illegal rectangle arguments: ~s ~s ~s ~s"
  475.                   left top right bottom))
  476.           (top
  477.            (setf (pref rect rect.topleft) (make-point left nil))
  478.            (setf (pref rect rect.bottomright) (make-point top nil)))
  479.           (t (%setf-macptr rect left))))
  480. )
  481.  
  482. (defmacro with-font-spec (font-spec &body body)
  483.   (if (and (listp font-spec) (every #'constantp font-spec))
  484.     (multiple-value-bind (ff ms) (font-codes font-spec)
  485.       `(with-font-codes ,ff ,ms ,@body))
  486.     (let ((ff (gensym))
  487.           (ms (gensym)))
  488.       `(multiple-value-bind (,ff ,ms) (font-codes ,font-spec)
  489.          (with-font-codes ,ff ,ms ,@body)))))
  490.  
  491. (defmacro with-pen-state ((&key pnLoc pnSize pnMode pnPat pnPixPat) &body body)
  492.   (let ((state (gensym)))
  493.     `(rlet ((,state :PenState))
  494.        (require-trap #_GetPenState :ptr ,state)
  495.        (unwind-protect
  496.          (progn
  497.            ,@(when pnLoc    `((require-trap #_MoveTo :long ,pnLoc)))
  498.            ,@(when pnSize   `((require-trap #_PenSize :long ,pnSize)))
  499.            ,@(when pnMode   `((require-trap #_PenMode :signed-integer ,pnMode)))
  500.            ,@(when pnPat    `((require-trap #_PenPat :ptr ,pnPat)))
  501.            ,@(when pnPixPat `((require-trap #_PenPixPat :ptr ,pnPixPat)))
  502.            ,@body)
  503.          (require-trap #_SetPenState :ptr ,state)))))
  504. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  505. ;; end of macros from quickdraw-u.lisp
  506.  
  507. (defun set-page-range (prec pages-to-print)
  508.   (hset prec :tprint.prjob.iFstpage 1)
  509.   (hset prec :tprint.prjob.iLstpage pages-to-print))
  510.  
  511. (defun copy-handle (handle)
  512.   (rlet ((h :pointer))
  513.     (setf (%get-ptr h) handle)
  514.     (#_HandToHand h)
  515.     (%get-ptr h)))
  516.  
  517. (defvar *printing* nil "Printing not in progress")
  518. (defvar *print-record-window* nil "window containg the view being printed")
  519. (defvar *mcl-get-print-record* #'get-print-record)
  520. (defparameter *debug* nil)              ;  for debugging only
  521. (defparameter *print-error* nil "The printing error in the form printer-condition")
  522. (defvar *print-hc-prec*)                ; the default print-record
  523.  
  524. ;; condition for printer errors
  525. (define-condition printer-condition (error)
  526.   (phase code cond)
  527.   (:report (lambda (condition stream)
  528.              (with-slots (phase code cond) condition
  529.                (if cond
  530.                  (format stream "Printer error ~s" cond)  
  531.                  (format stream "Printer error ~s in phase ~s" code phase))))))
  532.  
  533. ;; condition for a user-cancel for a print operation
  534. (define-condition user-cancel (printer-condition))
  535.  
  536.  
  537.  
  538. ;; functions for converting coordinates from one system to another
  539. (defun convert-offset (window container offset)
  540.   ;; If the container is a view, returns in window coordinates, 
  541.   ;; the point offset which is expressed in container coordinates
  542.   ;; Otherwise returns the offset.
  543.   (subtract-points 
  544.    (if container
  545.      (convert-coordinates #@(0 0) container window)
  546.      #@(0 0))
  547.    offset))
  548.  
  549. (defmethod window-view-corners ((self view) &optional (offset #@(0 0)))
  550.   ;; returns the coordinates of the view corners in window coordinates
  551.   ;; offset by offset
  552.   (let ((container (view-container self))
  553.         (window (view-window self)))
  554.     (multiple-value-bind (topLeft bottomRight)
  555.                          (view-corners self)
  556.       (setq offset (convert-offset window container offset))
  557.       (values (add-points topLeft offset) (add-points bottomRight offset)))))
  558.  
  559. (defmethod window-view-corners ((self dialog-item)  &optional (offset #@(0 0)))
  560.   ;; returns the coordinates of the view corners of a dialog item
  561.   ;; in window coordinates offset by offset
  562.   (let ((container (view-container self))
  563.         (window (view-window self)))
  564.     (multiple-value-bind (topLeft bottomRight)
  565.                          (view-corners self)
  566.       (setq offset (convert-offset window container offset))
  567.       (values (add-points topLeft offset) (add-points bottomRight offset)))))
  568.  
  569. ;;; Modified routines from print-utils.lisp for printing the contents of a views
  570. ;;; converted from MCL1.3.2
  571. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  572. ;;
  573. ;;hardcopy.lisp
  574. ;;
  575. ;;
  576. ;;copyright 1988-89 Apple Computer, Inc.
  577. ;;
  578. ;; defines a very basic printing routine for windows
  579. ;;
  580. ;; Code taken from Apple and Bill Kornfeld and played with a bit to get
  581. ;; something working.  Trying to change the wptr and
  582. ;; then doing a view-draw-contents fails --- LISP unexpectantly quits.
  583. ;; view-draw-contents without changing the window pointer
  584. ;; causes a print job to be sent to the printer but nothing comes out.
  585. ;; Using a print-contents function that just makes the appropriate 
  586. ;; calls seems to work ok. The basic print-contents
  587. ;; quickdraw functions for text, views and windows are defined here. 
  588. ;; Some extra print-contents functions for other items is defined in
  589. ;; odin-printing.lisp -- DEH 6/20/91
  590.  
  591. ;;;------------------ Printer constants----------------------------------------
  592. (defconstant $err-printer 94)
  593. (defconstant $err-printer-load 95)
  594. (defconstant $err-printer-start 97)
  595.  
  596. ;;;------------------ Picture comment operand ---------------------------------
  597. (defconstant $set-line-width 182 "Picture comment for setting line width")
  598.  
  599. ;;;------------------ Routine for trapping printer errors----------------------
  600. (defun printer-ok (&optional (errnum $err-printer)
  601.                              &aux (print-error (#_prError)))
  602.   ;; Checks for a printer error for the last printer command
  603.   ;; If there was an error, sets *printing* to nil
  604.   ;;   and if there has not been a previous printing error
  605.   ;;   sets the *print-error* to `(,errnum ,error)
  606.   (if (zerop print-error)
  607.     t
  608.     (progn
  609.       (unless *print-error*
  610.         (setq *print-error* (make-condition 'printer-condition))
  611.         (setf (slot-value *print-error* 'phase) errnum
  612.               (slot-value *print-error* 'code) print-error
  613.               (slot-value *print-error* 'cond) nil))
  614.       (setq *printing* nil)
  615.       (signal 'user-cancel))))
  616.  
  617. (defmacro check-printer-ok (form &optional (errnum $err-printer))
  618.   "Checks that the printer is ok after the execution of the form"
  619.   `(progn
  620.      ,form
  621.      (if (printer-ok ,errnum)
  622.        t
  623.        (throw :cancel nil))))
  624.  
  625. (defun get-printer-error ()
  626.   ;; returns nil or the the last non-zero printer error 
  627.   *print-error*)
  628.  
  629. ;;;------------------ The basic print-contents functions-----------------------
  630. (defmethod print-contents ((v window) &optional (offset #@(0 0)))
  631.   "a window draws a box around itself and
  632.    then asks its subviews to print themselves"
  633.   ;;first frame it
  634.   (multiple-value-bind (top-left bottom-right)
  635.                        (window-view-corners v offset)
  636.     (ccl::with-rectangle-arg (r top-Left bottom-right) 
  637.       (#_FrameRect r)))
  638.   (dovector (sv (view-subviews v))
  639.     (print-contents sv offset)))
  640.  
  641. (defmethod print-contents ((v view) &optional (offset #@(0 0)))
  642.   "a view just asks its subviews to print themselves"
  643.     (dovector (sv (view-subviews v))
  644.       (print-contents sv offset)))
  645.  
  646. (defmethod print-contents ((sv ccl::basic-editable-text-dialog-item)
  647.                            &optional (offset #@(0 0)))
  648.   "editable text uses textbox -- takes into account font and the justification"
  649.     (multiple-value-bind (top-left bottom-right)
  650.                          (window-view-corners sv offset)
  651.     (with-font-spec (view-font sv)
  652.       (ccl::with-rectangle-arg (r top-Left bottom-right)
  653.         (with-pstrs ((pstring (dialog-item-text sv)))
  654.           (#_TextBox :ptr (%inc-ptr pstring 1)
  655.            :long (length (dialog-item-text sv))
  656.            :ptr r
  657.            :word (slot-value sv 'ccl::text-justification)))))))
  658.  
  659. (defmethod print-contents ((sv static-text-dialog-item) &optional (offset #@(0 0)))
  660.   "static text uses textbox -- take into account font and the justification"
  661.   (multiple-value-bind (top-left bottom-right)
  662.                        (window-view-corners sv offset)
  663.     (with-font-spec (view-font sv)
  664.       (ccl::with-rectangle-arg (r top-Left bottom-right)
  665.         (with-pstrs ((pstring (dialog-item-text sv)))
  666.           (#_TextBox :ptr (%inc-ptr pstring 1)
  667.            :long (length (dialog-item-text sv))
  668.            :ptr r
  669.            :word (slot-value sv 'ccl::text-justification)))))))
  670.  
  671. (defmethod print-contents ((sv button-dialog-item)  &optional (offset #@(0 0)))
  672.   (multiple-value-bind (top-left bottom-right)
  673.                        (window-view-corners sv offset)
  674.     (ccl::with-rectangle-arg (r top-left bottom-right)
  675.       (with-font-spec (view-font sv)
  676.         (with-pstrs ((pstring (dialog-item-text sv)))
  677.           (#_TextBox :ptr (%inc-ptr pstring 1)
  678.            :long (length (dialog-item-text sv))
  679.            :ptr r :word 1)))
  680.       ;;; end of with-font-spec
  681.       (with-pen-state (:pnSize #@(1 1)
  682.                                :pnMode #$PATOR
  683.                                :pnPat *black-pattern*)
  684.           (decf (rref r :rect.left)
  685.                 (floor (dialog-item-width-correction sv) 2))
  686.           (incf (rref r :rect.right)
  687.                 (floor (dialog-item-width-correction sv) 2))
  688.           (#_FrameRoundRect :ptr r :word 10 :word 6)))))
  689.  
  690. (defmethod print-contents ((sv simple-view) &optional offset)
  691.   (declare (ignore offset))
  692.   "default if all else fails do nothing"
  693.   t)
  694. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  695. ;;; End of modified routines from print-utils.lisp
  696.  
  697. ;;;------------------ handles - checking validity and removing -------------------
  698. (defun valid-handle (handle)
  699.   (when (and handle
  700.              (handlep handle)
  701.              (pointerp handle)
  702.              (macptrp handle)
  703.              (not (equal handle (%null-ptr))))
  704.     handle))
  705.  
  706. (defun dispose-handle (handle)
  707.   (when (valid-handle handle)
  708.       (#_disposeHandle handle)))
  709.  
  710. ;;;---------retrieving and changing the value of an internal print-record---------
  711. ;; routines do not allocate new print records 
  712. (defmethod prec-get ((self view))
  713.   (view-get self :prec))
  714.  
  715. (defmethod prec-get ((self t))
  716.   (when (boundp '*print-hc-prec*)
  717.     *print-hc-prec*))
  718.  
  719. (defmethod prec-put ((self view) value)
  720.   (view-put self :prec value))
  721.  
  722. (defmethod prec-put ((self t) value)
  723.   (setq *print-hc-prec* value))
  724.  
  725. (defmacro clean-catch-cancel (flag &body body)
  726.   ;; When debugging print the flag
  727.   ;; Execute the body unwind-protected while catching
  728.   ;; cancels, errors, aborts and breaks
  729.   (let ((old-state (gensym)))
  730.    `(let ((,old-state *break-on-errors*))
  731.      (unwind-protect
  732.       (handler-case
  733.        (restart-case
  734.          (catch :cancel
  735.            (when *debug* (format t "~&--->~a~%" ,flag))
  736.            (setq *break-on-errors* nil)
  737.            ,@body)
  738.          (abort () (message-dialog "Printing aborted.")
  739.                 (stop-printing))
  740.          (error (condition) (stop-printing condition)))
  741.        (error (condition) (setq *printing* nil) condition))
  742.       (setq *break-on-errors* ,old-state)))))
  743.  
  744. ;;;---------determining the window containing the view (if any)---------
  745. ;;  for views returns
  746. ;;    either the window containing the view
  747. ;;    or the outermost view containing the view
  748. ;;  for all other objects returns the object
  749.  
  750. (defmethod containing-window ((view window))
  751.   view)
  752.  
  753. (defmethod containing-window ((sub-view view))
  754.   (loop with new-view
  755.         do (setq new-view (view-container sub-view))
  756.         while new-view
  757.         do (setq sub-view new-view)
  758.         finally (return sub-view)))
  759.  
  760. (defmethod containing-window ((self t))
  761.   self)
  762.  
  763. ;;;---------allocating, modifying and updating the internal print records---------
  764. (defmethod remove-view-from-window :after ((subview view))
  765.   (remove-prec subview))
  766.  
  767. ;; file names associated with views
  768. (defmethod view-file-name ((window fred-window))
  769.   (slot-value window 'ccl::my-file-name))
  770.  
  771. (defmethod view-file-name ((self t))
  772.   nil)
  773.  
  774. ;;;---------manipulating the internal print records---------
  775. (defmethod remove-prec ((self t))
  776.   ;; clean up the internal tprint handle (if any)
  777.   (dispose-handle (prec-get self))
  778.   (prec-put self nil))
  779.  
  780. (defmethod replace-prec ((self t) new-value)
  781.   ;; clean up the internal tprint handle (if any)
  782.   (let ((old-value (prec-get self)))
  783.     (unless (eq old-value new-value)
  784.       (remove-prec self)
  785.       (prec-put self new-value))
  786.     new-value))
  787.  
  788. (defmethod update-file-prec ((self t) prec &optional file-name)
  789.   ;; Saves a copy of the internal print record as a resource. 
  790.   ;; Called during a page setup and after saving a file (in this
  791.   ;; case the file-name argument is supplied 
  792.   (let ((filename (or file-name (view-file-name self)))
  793.         new-prec
  794.         old-prec)
  795.     (when (valid-handle prec)
  796.       (when (pathnamep filename)
  797.         (with-open-resource-file (refnum filename :if-does-not-exist :create)
  798.           (when *debug* (print-record prec :tprint) (terpri))
  799.           (setq old-prec (get-resource :prec 128 :errorp nil))
  800.           (when (valid-handle old-prec)
  801.             (remove-resource old-prec)
  802.             (dispose-handle old-prec))
  803.           (setq new-prec (copy-handle prec))
  804.           (when *debug* (print-record prec :tprint) (terpri))
  805.           ;; from Inside Macintosh I-123
  806.           (#_HNoPurge new-prec)
  807.           (add-resource new-prec :prec 128) 
  808.           (#_changedResource new-prec)
  809.           (write-resource new-prec)
  810.           (#_HPurge new-prec)
  811.           new-prec)))))
  812.  
  813. (defmethod get-prec ((self t))
  814.   (let (printer-record
  815.         (file-name (view-file-name self))
  816.         (view-print-record (prec-get self))
  817.         create)
  818.     ;; retrieves and possibly initializes the private print record
  819.     ;; if the print record exists and is a valid handle
  820.     ;;   returns the handle
  821.     ;; otherwise initializes the private print record
  822.     ;;   tries to read the :prec resource from the view-file-name
  823.     ;;    if successful
  824.     ;;     stores and returns a copy of the resource (handle)  
  825.     ;;    otherwise
  826.     ;;     creates a default print record using default-prec
  827.     ;;  
  828.     (cond 
  829.      ((valid-handle view-print-record) view-print-record)
  830.      ((null (pathnamep file-name)) (create-default-prec self))
  831.      (t (with-open-resource-file (refnum file-name :if-does-not-exist nil)
  832.           (cond 
  833.            ((or (null refnum) 
  834.                 (null (setq printer-record (get-resource :prec 128 :errorp nil))))
  835.             (setq view-print-record (create-default-prec self)
  836.                   create t))
  837.            (t (remove-prec self)
  838.               (setq view-print-record (copy-record printer-record :tprint))
  839.               (replace-prec self view-print-record)))
  840.           (when create
  841.             (update-file-prec self view-print-record))
  842.           view-print-record)))))
  843.  
  844. (defmethod create-default-prec ((self t))
  845.   (let (view-print-record)
  846.     (remove-prec self)
  847.     (setq view-print-record (default-prec self))
  848.     (replace-prec self view-print-record)
  849.     (update-file-prec self view-print-record)
  850.     view-print-record))
  851.  
  852. (defmethod get-print-prec ((self t))
  853.   (let ((outer-container (containing-window self)))
  854.     (cond ((null outer-container) (get-prec t))
  855.           ((eq self outer-container) (get-prec self))
  856.           (outer-container (get-prec outer-container))
  857.           (t (get-prec t)))))
  858.  
  859. ;; create a default print-record
  860. (defmethod default-prec ((self t))
  861.   (let (code
  862.         view-print-record)
  863.     (clean-catch-cancel 
  864.       :prec
  865.       (remove-prec self)
  866.       (setq view-print-record (#_NewHandle :errchk (record-length :TPrint)))
  867.       (setq code (#_MemError))
  868.       (when (zerop code)
  869.         (replace-prec self view-print-record)
  870.         (if (not (valid-handle view-print-record))
  871.           (setq code "invalid-handle")
  872.           (progn
  873.             (check-printer-ok (#_PrintDefault :ptr view-print-record))
  874.             (setq code nil)))))
  875.     (if code
  876.       (remove-prec self)
  877.       view-print-record)))
  878.  
  879. #|
  880. ;; routines for changing some of the page setup attributes
  881.  
  882. (defmethod set-print-reduction ((self t) reduction)
  883.   (with-open-printer (print-record :view self)
  884.     (if (integerp reduction)
  885.       (if (macptrp print-record)
  886.         (let ((min (rref print-record :tprint.izoommin))
  887.               (max (rref print-record :tprint.izoommax)))
  888.           (if (<= min reduction max)
  889.             (rset print-record :tprint.prxinfo.ibandh reduction)
  890.             (error "~s must be between ~d and ~d" reduction min max)))
  891.         (error "~s is not a macintosh pointer" print-record))
  892.       (error "~s must be an integer" reduction)
  893.       )))
  894.  
  895. (defmethod set-print-orientation ((self t) orientation)
  896.   (with-open-printer (print-record :view self)
  897.     (if (macptrp print-record)
  898.       (let* ((old (rref print-record :tprint.prstl.wdev))
  899.              (bit (ecase orientation
  900.                     (landscape 0)
  901.                     (portrait 1)))
  902.              ;; experimentally determined that bit one controls orientation
  903.              ;; is this always true?
  904.              (new (dpb bit (byte 1 1) old)))
  905.         (rset print-record :tprint.prstl.wdev new))
  906.       (error "~s is not a macintosh pointer" print-record)
  907.       )))
  908. |#
  909.  
  910. ;; routines for allocating/deallocating the tprint handle for printing
  911.  
  912. (defun stop-printing (&optional condition)
  913.   ;; stop printing
  914.   (setq *printing* nil
  915.         *print-error* (make-condition 'printer-condition))
  916.   (if condition
  917.     (setf (slot-value *print-error* 'phase) nil
  918.           (slot-value *print-error* 'code) nil
  919.           (slot-value *print-error* 'cond) condition)
  920.     (setf (slot-value *print-error* 'phase) $err-printer
  921.           (slot-value *print-error* 'code) #$iPrAbort
  922.           (slot-value *print-error* 'cond) nil))
  923.   (#_PrSetError #$iPrAbort)
  924.   (error *print-error*))
  925.  
  926. (defun reset-printing ()
  927.   (setq *printing* nil)
  928.   (#_prSetError #$NoErr))
  929.  
  930. ;; the method for getting a fred print record
  931. (defmethod get-print-prec ((window fred-window))
  932.   (get-print-record))
  933.  
  934. (defmethod check-print-prec ((self t))
  935.   ;; gets the tprint handle and validates it 
  936.   ;; when successful, returns the tprint handle
  937.   ;; must be called when the printer is open (e.g. within with-printer-open)
  938.   (let ((local-prec (get-print-prec self)))
  939.     (when local-prec
  940.       (clean-catch-cancel 
  941.        :check-print
  942.        (check-printer-ok (#_prValidate :ptr local-prec :boolean))
  943.        local-prec))))
  944.  
  945. ;; the print status dialog box (print-dialog) displayed when printing in progress.
  946. (defclass print-dialog (window)
  947.   ()
  948.   (:default-initargs
  949.     :window-type :double-edge-box 
  950.     :view-position :centered 
  951.     :view-size #@(373 96) 
  952.     :close-box-p nil 
  953.     :view-font '("Chicago" 12 :srcor :plain)))
  954.  
  955. (defmethod initialize-instance ((window print-dialog) &rest initargs)
  956.   (apply #'call-next-method window initargs)
  957.   (add-subviews window
  958.                 (make-instance 'static-text-dialog-item
  959.                   :view-position #@(10 10)
  960.                   :view-size #@(151 40) 
  961.                   :dialog-item-text (format nil
  962.                                             "Printing in progress
  963. To cancel press ~a-." #\CommandMark)
  964.                   :view-nick-name 'title)
  965.                 
  966.                 (make-instance 'static-text-dialog-item 
  967.                   :view-position #@(10 72) 
  968.                   :view-size #@(120 18) 
  969.                   :dialog-item-text "Printing page")
  970.                 
  971.                 (make-instance 'static-text-dialog-item 
  972.                   :view-position #@(135 72) 
  973.                   :view-size #@(36 18) 
  974.                   :dialog-item-text ""
  975.                   :view-nick-name 'page)
  976.                 
  977.                 #|
  978. (make-instance 'button-dialog-item 
  979.   :view-position #@(302 72) 
  980.   :view-size #@(62 16) 
  981.   :dialog-item-text "Cancel" 
  982.   :dialog-item-action 
  983.   #'(lambda (item) item
  984.      (window-hide (view-window item))
  985.      (stop-printing)) 
  986.   :default-button nil)
  987. |#
  988.                 ))
  989.  
  990. (defvar *print-dialog*
  991.   (make-instance 'print-dialog :window-show nil)
  992.   "The printing progress dialog box")
  993.  
  994. ;; gets the dialog box asscoiated with print progress
  995. (defmethod get-print-dialog ((self t) &key (display nil) (wait t))
  996.   (declare (ignore self))
  997.   "Displays the printer progress dialog box and waits for 1 second."
  998.   (unless (and *print-dialog* (wptr *print-dialog*) (pointerp (wptr *print-dialog*)))
  999.     (setq *print-dialog* (make-instance 'print-dialog :window-show nil)))
  1000.   (when (and *printing* display) 
  1001.     (with-focused-view *print-dialog*
  1002.       (window-show *print-dialog*)))
  1003.   (when wait (sleep 1))
  1004.   *print-dialog*)
  1005.  
  1006. ;; default method for removing the print progress dialog box, 
  1007. ;; specialize for other views
  1008. (defmethod remove-print-dialog ((self t))
  1009.   (when (and *print-dialog* (wptr *print-dialog*))
  1010.     (window-close *print-dialog*))
  1011.   (setq *print-dialog* nil))
  1012.  
  1013. ;; default method for indicating printing progress, specialize for other views
  1014. ;; Note: does not update the page field when background printing is off
  1015. (defmethod set-page-number ((self t) page-no &key (display nil))
  1016.   "Update the page number field for printing"
  1017.   (let* ((print-dialog (get-print-dialog self :display display :wait display))
  1018.          (page-field (view-named 'page print-dialog)))
  1019.     ; force the window to be updated
  1020.     (with-focused-view print-dialog
  1021.       (set-dialog-item-text page-field (format nil "~3d" page-no))
  1022.       ;(event-dispatch)    ; fails to return when background printing is off
  1023.       (sleep 1))))            
  1024.  
  1025. ;; methods and functions for working with the printer port as a view
  1026. ;;  similar to the wmgr-view functions in oodles-of-utils:simple-view-ce.lisp
  1027. ;; Supplied by Bill St. Clair at Apple.
  1028.  
  1029. (defclass printer-view (simple-view)
  1030.   ((clip-region :initform nil :accessor printer-view-clip-region)))
  1031.  
  1032. (defmethod view-origin ((view printer-view))
  1033.   (let ((wptr (wptr view)))
  1034.     (if wptr
  1035.       (rref wptr :grafport.portrect.topleft)
  1036.       #@(0 0))))
  1037.  
  1038. (defmethod view-clip-region ((view printer-view))
  1039.   (let ((macptr (printer-view-clip-region view)))
  1040.     (unless (typep macptr 'macptr)
  1041.       (setq macptr
  1042.             (setf (printer-view-clip-region view) (%null-ptr))))
  1043.     (%setf-macptr macptr (rref (wptr view) :grafport.cliprgn))
  1044.     macptr))
  1045.  
  1046. (defun make-printer-view (printer-port)
  1047.   (let ((topleft (rref printer-port :grafport.portrect.topleft))
  1048.         (botright (rref printer-port :grafport.portrect.botright)))
  1049.     (make-instance 'printer-view
  1050.       :wptr printer-port
  1051.       :view-position topleft
  1052.       :view-size (subtract-points botright topleft))))
  1053.  
  1054. ;;  basic macros for using a printer, printing a document and printing a page.
  1055. (defmacro with-open-page ((hardcopy-ptr page-size offset &key (local t))
  1056.                           &rest body)
  1057.   ;; Opens a printer page
  1058.   ;; executes the body
  1059.   ;; closes the printer upon termination (even when in error)
  1060.   ;; returns the result of executing the body
  1061.   (let ((r (gensym))
  1062.         (vals (gensym)))
  1063.     `(let (,vals)
  1064.        (clean-catch-cancel 
  1065.         :open-page
  1066.         (rlet ((,r :rect :topLeft #@(0 0) :bottomRight ,page-size))
  1067.           (when ,local (require-trap #_offsetRect :ptr ,r :long ,offset))
  1068.           (unwind-protect
  1069.             (clean-catch-cancel 
  1070.              :inner-open-page
  1071.              (setq ,vals
  1072.                    (multiple-value-list
  1073.                     (with-clip-rect ,r 
  1074.                       (check-printer-ok 
  1075.                        (require-trap #_PrOpenPage
  1076.                                      :ptr ,hardcopy-ptr :ptr (if ,local ,r  (%null-ptr))))
  1077.                       ,@body))))
  1078.             (check-printer-ok (require-trap #_PrClosePage :ptr ,hardcopy-ptr)))))
  1079.        (values-list ,vals))))
  1080.  
  1081. (defmacro with-open-doc (hardcopy-ptr prec &rest body)
  1082.   ; _PrOpenDoc puts up a dialog window
  1083.   ; In order to process events within the body, we must call
  1084.   ; event-dispatch, otherwise windows will not be updated
  1085.   ; Opens the printer document
  1086.   ; Executes the body of code with the local variable
  1087.   ;   hardcopy-ptr bound to the printer GrafPort
  1088.   ;   prec is a handle to the TPrint record
  1089.   ; Closes the printer document upon termination (even when in error)
  1090.   ; Returns the result of executing the body
  1091.   ;;
  1092.   ; without-interrupts appears in the same place as (window-hardcopy fred-window)
  1093.   ; before the open-doc (decinest appears at location 332, open-doc at 360-362)
  1094.   (let ((vals (gensym))
  1095.         (stRec (gensym))
  1096.         (printer-view (gensym)))
  1097.     `(let ((,hardcopy-ptr 
  1098.             (require-trap #_PrOpenDoc :ptr ,pRec :ptr (%null-ptr) :ptr (%null-ptr) :ptr))
  1099.            ,vals
  1100.            ,printer-view)
  1101.        (without-interrupts
  1102.         (clean-catch-cancel 
  1103.           :open-doc
  1104.           (unwind-protect
  1105.             (clean-catch-cancel 
  1106.               :port
  1107.               (setq ,printer-view (make-printer-view ,hardcopy-ptr))
  1108.               (check-printer-ok nil $err-printer-start)
  1109.               (setq ,vals
  1110.                     (multiple-value-list
  1111.                      (with-focused-view ,printer-view 
  1112.                        ,@body))))
  1113.             (check-printer-ok (require-trap #_PrCloseDoc :ptr ,hardcopy-ptr)))
  1114.           (when (= (href ,prec :tprint.prJob.bjDocLoop) #$bSpoolLoop)
  1115.             (%stack-block ((,StRec (record-length :tprStatus)))
  1116.               (check-printer-ok (require-trap #_PrPicFile
  1117.                                  :ptr ,pRec
  1118.                                  :ptr (%null-ptr)
  1119.                                  :ptr (%null-ptr)
  1120.                                  :ptr (%null-ptr)
  1121.                                  :ptr ,StRec)))))
  1122.         (values-list ,vals)))))
  1123.  
  1124. (defmacro with-open-printer ((prec &key (view t) (show-dialog? nil)) &rest body)
  1125.   ; Opens the printer
  1126.   ; Executes the body of code with the local variable
  1127.   ;  Closes the printer upon termination (even when in error)
  1128.   ;; returns the result of executing the body
  1129.   
  1130.   (let ((vals (gensym)))
  1131.     `(let (,vals ,prec)
  1132.        (unwind-protect
  1133.          (clean-catch-cancel 
  1134.           :open-print
  1135.           (setq ,vals
  1136.                 (multiple-value-list
  1137.                  (unless *printing*
  1138.                    (check-printer-ok (require-trap #_PrOpen) $err-printer-load)
  1139.                    (setq *printing* t)
  1140.                    (when (and (setq ,prec (get-print-prec ,view))
  1141.                               (check-print-prec ,view)
  1142.                               (or (null ,show-dialog?) 
  1143.                                   (with-cursor *arrow-cursor* 
  1144.                                     (require-trap #_PrJobdialog :ptr ,prec :boolean))))
  1145.                      ,@body)))))
  1146.          (check-printer-ok (require-trap #_PrClose))
  1147.          (setq *printing* nil))
  1148.        (values-list ,vals))))
  1149.  
  1150. ;; generalized page-setup routines for objects that are not fred windows
  1151. (defmethod page-setup ((self t))
  1152.   ;; Atempts to retrieve a valid tprint handle
  1153.   ;; If successful displays the page setup dialog using the print record
  1154.   ;; Returns t when successful
  1155.   (with-cursor *arrow-cursor*
  1156.     (with-open-printer (prec :view self)
  1157.       (when *debug* (print-record prec :tprint) (terpri))
  1158.       (check-printer-ok (#_PrStlDialog :ptr prec :boolean))
  1159.       (update-file-prec self prec)
  1160.       (when *debug* (print-record prec :tprint) (terpri))
  1161.       t)))
  1162.  
  1163. ;; page setup
  1164. ;;   for fred windows
  1165. (defmethod page-setup ((window fred-window))
  1166.   (let ((*print-record-window* window))
  1167.     (print-style-dialog)))
  1168.  
  1169. ;; routines for determining the topLeft and bottomRight corners
  1170. ;; of the printer-page
  1171. (defun get-page-size (pRec)
  1172.   (subtract-points (href pREC :tprint.prInfo.rpage.bottomRight)
  1173.                    (href pREC :tprint.prInfo.rpage.topLeft)))
  1174.  
  1175. (defmethod page-size ((self t))
  1176.   (with-open-printer (prec :view self)
  1177.     (get-page-size prec)))
  1178.  
  1179. (defmethod page-size ((window fred-window))
  1180.   (with-open-printer (prec :view window)
  1181.     (get-page-size prec)))
  1182.      
  1183. ;; Routines for computing the corners of rectangular pictures and windows
  1184.  
  1185. (defun picture-corners (picture page-size)
  1186.   (declare (ignore page-size))
  1187.   ;; return the topleft and bottomRight corners of the picture
  1188.   (when (handlep picture)
  1189.     (values
  1190.      (rref picture picture.picframe.topleft)
  1191.      (rref picture picture.picframe.bottomRight))))
  1192.  
  1193. (defmethod window-document-corners ((view window) page-size)
  1194.   (declare (ignore page-size))
  1195.   ;; Computes the topLeft and bottomRight corners of the rectangle
  1196.   ;; for the view. Specialize to handle scrolling windows
  1197.   (view-corners view))
  1198.  
  1199. (defmethod view-document-corners ((view view) page-size)
  1200.   (declare (ignore page-size))
  1201.   ;; Computes the topLeft and bottomRight corners of the rectangle
  1202.   ;; for the view. Specialize to handle scrolling windows
  1203.   (view-corners view))
  1204.  
  1205. ;; routines for computing the page layout (document size in pages-h x pages-v)
  1206. (defun compute-page-size (document-size page-size)
  1207.   ;; returns the point representing the document-size in pages width x depth
  1208.   (let* ((page-h (ceiling (point-h document-size) (point-h page-size)))
  1209.          (page-v (ceiling (point-v document-size) (point-v page-size))))
  1210.     (values
  1211.      page-h
  1212.      page-v
  1213.      (* page-h page-v))))
  1214.  
  1215. ;; not currently used, can be used within the print-fn for a document-hardcopy
  1216. ;; to determine the current page number, and row/column index
  1217. (defun compute-page-topLeft (page-size pages-h pages-v page-no)
  1218.   ;; given the size of the page-rectangle (page-size)
  1219.   ;;       the dimensions of the document in pages pages-h x pages-v
  1220.   ;;       the page number being printed
  1221.   ;; returns the page-no and the column/row position of the page
  1222.   ;;       and the coordinates of the upper left corner of the
  1223.   ;;       document corresponding to the page of size page-size
  1224.   (declare (ignore pages-v))
  1225.   (multiple-value-bind (real-v real-h)
  1226.                        (truncate page-no pages-h)
  1227.     (values
  1228.      page-no
  1229.      real-h
  1230.      real-v
  1231.     (make-point (* (point-h page-size) real-h)
  1232.                 (* (point-v page-size) real-v)))))
  1233.  
  1234. ;; default routines for printing a document and for determining its size
  1235. (defun default-document-hardcopy (view page-size page-no offset local)
  1236.   (declare (ignore view prRec page-size page-no offset local)))
  1237.  
  1238. (defun default-document-corners (view psize)
  1239.   (declare (ignore view))
  1240.   (values #@(0 0) psize))
  1241.  
  1242. (defun compute-page-layout (view page-size compute-doc-size)
  1243.   ;; uses the compute-doc-size function with view and page-size
  1244.   ;; to compute the size of the document in pages (pages-h x pages-v)
  1245.     (multiple-value-bind (top bottom)
  1246.                          (funcall (if (functionp compute-doc-size)
  1247.                                     compute-doc-size
  1248.                                     #'ccl::default-document-corners)
  1249.                                   view page-size)
  1250.       (compute-page-size (subtract-points bottom top) page-size)))
  1251.  
  1252.  
  1253. ;; hardcopy routines for documents, windows and pictures
  1254.  
  1255. ;;  General hardcopy routine
  1256. (defun document-hardcopy (print-fn document-corners &key (show-dialog? t) view (local t))
  1257.   (setq *print-error* nil)
  1258.   (let (offset 
  1259.         page-size v-dim h-dim (page-no 0))
  1260.     (get-print-dialog view)
  1261.     (with-cursor *arrow-cursor* 
  1262.       (with-open-printer (prec :view view :show-dialog? show-dialog?)
  1263.         (with-cursor *watch-cursor*
  1264.           (when *printing*
  1265.             (clean-catch-cancel 
  1266.              :doco
  1267.               (unwind-protect
  1268.                 (setq page-size (get-page-size prec))
  1269.                 (multiple-value-bind (pages-h pages-v pages)
  1270.                                      (compute-page-layout view page-size document-corners)
  1271.                   (decf pages-h)
  1272.                   (decf pages-v)
  1273.                   (unless (functionp print-fn)
  1274.                     (setq print-fn #'default-document-hardcopy))
  1275.                   (window-select (get-print-dialog view :display t))
  1276.                   (event-dispatch)
  1277.                   (with-open-doc hardcopy-ptr prec
  1278.                     (let* ((from-page (max 1 (href prec :tprint.prJob.iFstPage)))
  1279.                            (to-page (min pages (href prec :tprint.prJob.iLstPage)))
  1280.                            (pages-to-print (1+ (- to-page from-page))))
  1281.                       ;; print pages-to-print pages (from from-page to to-page)
  1282.                       ;; adjust the print record to print only pages-to-print pages
  1283.                       (set-page-range prec pages-to-print)
  1284.                       (loop for v-page fixnum from 0 to pages-v
  1285.                             do (setq v-dim (* (point-v page-size) v-page))
  1286.                             (loop for h-page fixnum from 0 to pages-h
  1287.                                   do (incf page-no)
  1288.                                   (when (<= from-page page-no to-page)
  1289.                                     ;; only print pages in the range from-page to to-page
  1290.                                     (decf pages-to-print)
  1291.                                     (setq h-dim (* (point-h page-size) h-page))
  1292.                                     (setq offset (make-point h-dim v-dim))
  1293.                                     (when *printing*
  1294.                                       (set-page-number view page-no :display t)
  1295.                                       (with-open-page (hardcopy-ptr page-size offset :local local)
  1296.                                         (funcall print-fn view page-size page-no offset local))))
  1297.                                   
  1298.                                   while (and *printing*   ; stop when printing canceled
  1299.                                              (> pages-to-print 0)))   ; or no pages to print
  1300.                             
  1301.                             ; stop when no pages remain to print or printing is cancelled
  1302.                             while (and *printing* (> pages-to-print 0)))))))))
  1303.           (unless *printing* 
  1304.             (unless *print-error*
  1305.               (setq *print-error* (make-condition 'printer-condition))
  1306.               (with-slots (phase code cond) *print-error*
  1307.                 (setq phase $err-printer
  1308.                       code #$iPrAbort
  1309.                       cond nil))
  1310.               (#_PrSetError #$iPrAbort)))
  1311.           (remove-print-dialog view)
  1312.           (setq *printing* nil)
  1313.           (null *print-error*))))))
  1314.  
  1315. ;; Internal routine for printing the contents of a views
  1316. (defmethod view-print-contents ((subview view)
  1317.                                 page-size page-no offset local)
  1318.   (declare (ignore page-size page-no))
  1319.   (let ((*print-record-window* subview))
  1320.     (print-contents subview (if local #@(0 0)
  1321.                                 offset))))
  1322.  
  1323. ;; Print contents of a non-fred window, fred windows already defined
  1324. (defmethod window-hardcopy ((v window) &optional (show-dialog? t))
  1325.   (document-hardcopy #'view-print-contents #'window-document-corners
  1326.                      :view  v
  1327.                      :show-dialog? show-dialog?
  1328.                      :local t))
  1329.  
  1330. ;; Print a picture on the printer
  1331. (defun picture-hardcopy (picture &optional (show-dialog? t))
  1332.   (when (handlep picture)
  1333.     (with-dereferenced-handles ((picture-ptr picture))
  1334.       (flet ((pict-draw (view page-size page-no offset local)
  1335.                (declare (ignore view page-no))
  1336.                (multiple-value-bind (topLeft bottomRight)
  1337.                                     (picture-corners picture page-size)
  1338.                  (with-rectangle-arg (r topLeft bottomRight)
  1339.                    (unless local (#_offsetRect :ptr r :long (subtract-points #@(0 0) offset)))
  1340.                    (#_drawPicture :ptr picture :ptr r))))
  1341.              (pict-size (view page-size)
  1342.                (declare (ignore view))
  1343.                (picture-corners picture page-size)))
  1344.         (declare (dynamic-extent #'pict-draw #'pict-size))
  1345.         (document-hardcopy #'pict-draw #'pict-size :show-dialog? show-dialog?)))))
  1346.  
  1347.  
  1348. ;;;; functions to setup the environment for printing
  1349. ;; changes the page setup menu item to use the new Page Setup function
  1350. (defun fix-file-menu ()
  1351.   (let ((page-setup (find-menu-item *file-menu* "Page Setup"))
  1352.         (print (find-menu-item *file-menu* "Print")))
  1353.     (when page-setup
  1354.       (change-class page-setup 'window-menu-item)
  1355.       (setf (menu-item-action-function page-setup)
  1356.             #'(lambda (window)
  1357.                 (eval-enqueue `(page-setup ,window)))))
  1358.     (when print
  1359.       (setf (menu-item-action-function print)
  1360.             #'(lambda (window)
  1361.                 (eval-enqueue `(ccl::window-hardcopy ,window)))))
  1362.     (setq *printing* nil)))
  1363.  
  1364. (defun remove-hc-prec ()
  1365.   ;; clean up the internal tprint handle
  1366.   ;; modify if you need to clean up others
  1367.   (remove-prec t))
  1368.                 
  1369. (defun setup-printing ()
  1370.   ;; remove and then add #'fix-file-menu to end of *lisp-startup-functions*
  1371.   (setq *lisp-startup-functions*
  1372.         (remove 'fix-file-menu *lisp-startup-functions* :key #'function-name))
  1373.   (setq *printing* nil)
  1374.   (push #'fix-file-menu *lisp-startup-functions*)
  1375.   (setq *save-exit-functions*
  1376.         (remove 'remove-hc-prec *save-exit-functions* :key #'function-name))
  1377.   (push #'remove-hc-prec *save-exit-functions*))
  1378.   
  1379. ;; setup the printing enviroment and fix the Page setup menu item
  1380. (setup-printing)
  1381. (fix-file-menu)
  1382.  
  1383. ;; augment the window-hardcopy, window-save, print-style-dialog
  1384. ;; and get-print-record routines
  1385. (advise ccl::window-hardcopy
  1386.         (let* ((*print-record-window* (car arglist))
  1387.                (*hc-prec* (with-open-printer (prec :view *print-record-window*)
  1388.                             (get-print-prec *print-record-window*))))
  1389.           (:do-it))
  1390.         :when :around)
  1391.  
  1392. (advise ccl::window-save-file
  1393.         (let ((*print-record-window* (car arglist))
  1394.               window-file)
  1395.           (setq window-file (:do-it))
  1396.           (when window-file
  1397.             (with-open-printer (prec :view *print-record-window*)
  1398.               (get-print-prec *print-record-window*)
  1399.               (update-file-prec *print-record-window* 
  1400.                            (get-prec *print-record-window*)
  1401.                            window-file)))
  1402.           window-file)
  1403.         :when :around)
  1404.  
  1405. (advise ccl::print-style-dialog
  1406.         (let ((*print-record-window* (front-window))
  1407.               result)
  1408.           (setq result (:do-it))
  1409.           (with-open-printer (prec :view *print-record-window*)
  1410.             (get-print-prec *print-record-window*)
  1411.             (update-file-prec *print-record-window* (prec-get *print-record-window*)))
  1412.           result)
  1413.         :when :around)
  1414.  
  1415. (let ((*warn-if-redefine* nil)
  1416.       (*warn-if-redefine-kernel* nil))
  1417.   
  1418.   (defun get-print-record ()
  1419.     (if *print-record-window*
  1420.       (get-prec *print-record-window*)
  1421.       (funcall *mcl-get-print-record*)))
  1422.   
  1423.   )
  1424.  
  1425.  
  1426. #|
  1427. (defun make-print-demo ()
  1428.   "Create the experiment application"
  1429.   (let ((target-appl (choose-new-file-dialog :directory "ccl;print-demo")))
  1430.     (save-application target-appl
  1431.                       :excise-compiler nil    ; do want the compiler
  1432.                       :creator :glop
  1433.                       :clear-clos-caches nil ; otherwise we can't access classes
  1434.                       )))
  1435. (make-print-demo)
  1436. |#
  1437.  
  1438. #|
  1439. ;;;  Four printing examples and two examples of saving private print records
  1440. ;;;
  1441. ;;;  Four printing examples:
  1442. ;;;  - contents of a small window
  1443. ;;;  - a picture
  1444. ;;;  - contents of a large window
  1445. ;;;  - a general document
  1446.  
  1447. (defvar *w1*)
  1448. (defvar *test-window*)
  1449. (defvar *picture*)
  1450.  
  1451.  
  1452.  
  1453. ;;---------------------- printing the contents of a small window ------------------------
  1454. ;; Create a window with nested views and print it.
  1455. (setq *w1* (make-instance 'window
  1456.             :window-title "HI there"
  1457.             :view-size #@(300 300)
  1458.             :view-subviews
  1459.                (list (make-instance 'view
  1460.                    :view-position #@(20 20)
  1461.                    :view-size #@(150 130)
  1462.                    :view-subviews
  1463.                        (List (make-instance 'static-text-dialog-item
  1464.                                  :view-position #@(10 10)
  1465.                                  :view-size #@(130 40)
  1466.                                  :view-font '("Helvetica" :srcor :bold 12)
  1467.                                  :dialog-item-text
  1468.                                     "how now said the big brown cow")
  1469.                              (make-instance 'static-text-dialog-item
  1470.                                             :view-position #@(10 70)
  1471.                                             :view-size #@(130 60)
  1472.                                             :view-font '("Geneva" :srcor :underline 14)
  1473.                                             :dialog-item-text
  1474.                                             "there is a bunch of green cheese here on the moon")))
  1475.                      (make-instance 'button-dialog-item
  1476.                                             :view-position #@(160 160)
  1477.                                             :view-size #@(72 16)
  1478.                                             :dialog-item-text "Green"))))
  1479.  
  1480. (window-hardcopy *w1*)                  ; print the window
  1481.                                         ; Also select the window and do a file Print
  1482.  
  1483. ;;---------------------------- printing a picture -----------------------------
  1484. ;; Print a picture. The picture corresponds to a picture of the print-contents
  1485. ;; of the window w1 using a window twice the size. 
  1486. (let ((view-size (view-size *w1*)) mid-point)
  1487.   (when (and (boundp '*picture*) (handlep *picture*))
  1488.     (kill-picture *picture*))
  1489.   (with-focused-view *w1*
  1490.     (start-picture *w1* #@(0 0) (make-point (* 2 (point-h view-size))
  1491.                                             (* 2 (point-v view-size))))
  1492.     (print-contents *w1*)
  1493.     (setq *picture* (get-picture *w1*)))
  1494.  
  1495.   ;; draw the picture at half- in the bottom right corner of *w1*
  1496.   (window-select *w1*)
  1497.   (sleep 1)
  1498.   (setq mid-point (make-point (floor (point-h view-size) 2)
  1499.                               (floor (point-v view-size) 2)))
  1500.   (draw-picture *w1* *picture* mid-point (add-points (view-size *w1*) mid-point))
  1501.   (sleep 1)
  1502.   (print-record *picture* :picture) (terpri)
  1503.   (picture-hardcopy *picture*)              ; print the picture
  1504.   (kill-picture *picture*)                  ; remove the picture
  1505.   )
  1506.  
  1507.  
  1508. ;;;  - 
  1509. ;;-------------------- printing the contents of a large window ---------------------
  1510. ;;  Print the contents of a large dialog (918 x 708) 
  1511. (setq *test-window*
  1512.    (make-instance 'color-dialog
  1513.                :window-type :document-with-zoom 
  1514.                :view-position #@(100 100)
  1515.                :view-size #@(918 708)
  1516.                :view-font '("Chicago" 12 :SRCOR :PLAIN)
  1517.                :view-subviews
  1518.                (list (make-instance 'static-text-dialog-item
  1519.                                        :view-position #@(13 9)
  1520.                                        :view-size #@(56 16)
  1521.                                        :dialog-item-text "Untitled")
  1522.  
  1523.                      (make-instance 'editable-text-dialog-item
  1524.                                        :view-position #@(15 25)
  1525.                                        :view-size #@(84 16)
  1526.                                        :dialog-item-text "Untitled"
  1527.                                        :allow-returns nil)
  1528.  
  1529.                      (make-instance 'button-dialog-item
  1530.                                        :view-position #@(15 47)
  1531.                                        :view-size #@(62 16)
  1532.                                        :dialog-item-text "Untitled"
  1533.                                        :default-button nil)
  1534.  
  1535.                      (make-instance 'editable-text-dialog-item
  1536.                                        :view-position #@(381 683)
  1537.                                        :view-size #@(114 16)
  1538.                                        :dialog-item-text "bottom center"
  1539.                                        :allow-returns nil)
  1540.  
  1541.                      (make-instance 'editable-text-dialog-item
  1542.                                        :view-position #@(11 688)
  1543.                                        :view-size #@(84 16)
  1544.                                        :dialog-item-text "bottom left"
  1545.                                        :allow-returns nil)
  1546.  
  1547.                      (make-instance 'editable-text-dialog-item
  1548.                                        :view-position #@(375 20)
  1549.                                        :view-size #@(84 16)
  1550.                                        :dialog-item-text "top center"
  1551.                                        :allow-returns nil)
  1552.  
  1553.                      (make-instance 'editable-text-dialog-item
  1554.                                        :view-position #@(799 676)
  1555.                                        :view-size #@(84 16)
  1556.                                        :dialog-item-text "bottom right"
  1557.                                        :view-font
  1558.                                        '("New Century Schlbk"
  1559.                                          12 :SRCOR :PLAIN)
  1560.                                        :allow-returns nil)
  1561.  
  1562.                      (make-instance 'editable-text-dialog-item
  1563.                                        :view-position #@(818 20)
  1564.                                        :view-size #@(84 16)
  1565.                                        :dialog-item-text "top right"
  1566.                                        :view-font
  1567.                                        '("New Century Schlbk"
  1568.                                          12 :SRCOR :PLAIN)
  1569.                                        :allow-returns nil)))
  1570. )
  1571.  
  1572. (window-hardcopy *test-window*)           ; print the large dialog
  1573.  
  1574. ;;---------------------- printing a general document -----------------------
  1575. ;;  Print a document of size 552 x 1460 pixels
  1576. ;;  This requires two 8.5" x 11" pages at normal size (Reduce/Enlarge 100%)
  1577. ;;  At normal size prints two pages with 
  1578. ;;  "Now is the time for all good men to come to the aid" on the first page
  1579. ;;  twice on the first page at #@(50 50) and #@(50 100)
  1580. ;;  and with the string "When johnny comes marching home again" in the
  1581. ;;  relative positions #@(200 0) and #@(50 100) on the second page.
  1582. ;;  At 50% or smaller reduction, prints only the first page, reduced.
  1583. ;;  At 200% or greater reduction prints two pages, enlarged.
  1584.  
  1585. ;;  When 50% reduction, prints only one "page"
  1586. (defun my-hardcopy-fn (view page-size page-no offset local)
  1587.   (declare (ignore view page-size))
  1588.   (unless local (setq offset #@(0 0)))
  1589.   (let ((text "Now is the time for all good men to come to the aid"))
  1590.     (with-font-spec '("Times" 18 :srcor :plain)
  1591.       (if (= page-no 0)
  1592.         (#_moveTo :long (add-points #@(50 50) offset))
  1593.         (progn (#_moveTo :long (add-points #@(200 0) offset))
  1594.                (setq text "When johnny comes marching home again")))
  1595.       (with-returned-pstrs ((text-buff text))
  1596.         (#_DrawText :ptr text-buff :integer 1 :integer (length text)))
  1597.       (#_moveTo :long (add-points #@(50 100) offset))
  1598.       (with-returned-pstrs ((text-buff text))
  1599.         (#_DrawText :ptr text-buff :integer 1 :integer (length text)))
  1600.       )))
  1601.  
  1602. (defun my-document-corners (view page-size)
  1603.   (declare (ignore view page-size))
  1604.   ;; a document on 8.5 x 11 paper 1 wide and 2 high
  1605.   (values #@(0 0) (make-point 552 (* 2 730))))
  1606.  
  1607. (document-hardcopy #'my-hardcopy-fn #'my-document-corners)   ; print the document
  1608.  
  1609. ;;;  - 
  1610. ;;-------------------- changing the page setup atributes of a file ---------------------
  1611. ;; open an existing file in a fred window,
  1612. ;; change the page setup attributes and reopen the file 
  1613. (defvar *test-window*)
  1614. (defvar *file-name*)
  1615. (setq *test-window* (fred (choose-file-dialog :button-string "Edit")))
  1616. (setq *file-name* (view-file-name *test-window*))
  1617.  
  1618. ;; Change the page setup   
  1619. (page-setup *test-window*)
  1620. (window-close *test-window*)
  1621.  
  1622. ;; open the file again and see that the attributes have changed
  1623. (setq *test-window* (fred *file-name*))
  1624. (page-setup *test-window*)
  1625.  
  1626. ;; open the file and see that the :prec resource has been saved
  1627. (with-open-resource-file (refnum *file-name* :if-does-not-exist nil)
  1628.   (let (printer-record)
  1629.     (setq printer-record (get-resource :prec 128 :errorp nil))
  1630.     (print-db printer-record)
  1631.     (when (valid-handle printer-record)
  1632.       (print-record printer-record :tprint))))
  1633.  
  1634. ;;;  - 
  1635. ;;-------------------- views that store their print record in a slot ---------------------
  1636. ;;  the slot is ccl::my-print-record
  1637.  
  1638. (defclass print-view (view)
  1639.   ((my-print-record :initform nil)
  1640.    (my-file-name :initform nil)))
  1641.  
  1642. (defclass print-window (print-view window) nil)
  1643.  
  1644. (defmethod view-file-name ((view print-view))
  1645.   (slot-value view 'my-file-name))
  1646.  
  1647. (defmethod view-get ((view print-view) flag &optional option)
  1648.   (declare (ignore option))
  1649.   (if (equal flag :prec)
  1650.       (slot-value view 'my-print-record)
  1651.       (call-next-method)))
  1652.  
  1653. (defmethod view-put ((view print-view) flag value)
  1654.   (if (equal flag :prec)
  1655.     (setf (slot-value view 'my-print-record) value)
  1656.     (call-next-method)))
  1657.  
  1658. (setq *test-window* (make-instance 'print-window))
  1659. (setq *file-name* (choose-file-dialog))
  1660.  
  1661. ;; change the page setup attributes, they'll be saved with the file
  1662. (page-setup *test-window*)
  1663. (window-close *test-window*)
  1664.  
  1665. ;; create another window into the same "file"
  1666. ;; and see that the print-record has been restored.
  1667. (setq *test-window* (make-instance 'print-window))
  1668. (setf (slot-value *test-window* 'my-file-name) *file-name*)
  1669. (page-setup *test-window*)
  1670. |#
  1671.  
  1672.  
  1673. ;; Routines for changing the line width for PostScript devices
  1674. ;;  Routines can be used in build pictures
  1675. ;;  or within a document-hardcopy
  1676. ;; The routines change the printed output only for PostScript devices
  1677. ;; 
  1678. ;;  
  1679. (defun scale-line-width (scale)
  1680.   (unless (rationalp scale)
  1681.     (error "~A is not a Rational" scale))
  1682.   (let ((h (denominator scale))
  1683.         (v (numerator scale)))
  1684.     (let ((width-h (#_NewHandle (record-length :fixedPoint))))
  1685.       (unless (valid-handle width-h)
  1686.         (error "unable to allocate a ~a temporary record handle (~a bytes)."
  1687.                (record-length :fixedPoint)))
  1688.       (unwind-protect
  1689.         (progn
  1690.           (with-dereferenced-handles ((width-p width-h))
  1691.             (require-trap #_setpt (:pointer :point) width-p 
  1692.                           :signed-integer h 
  1693.                           :signed-integer v))
  1694.           (require-trap #_piccomment :word $set-line-width :word 4 :ptr width-h))
  1695.         (dispose-handle width-h)))))
  1696.  
  1697. (defun normal-line-width ()
  1698.   (scale-line-width 1))
  1699.  
  1700. #|
  1701. An example which creates two pictures, displays both at 400% scale,
  1702. and prints them.
  1703.  
  1704. Assumptions:
  1705.    The display device has a horizontal/vertical resolution of 72 pixels/inch
  1706.    The PostScript device resolution is 300 pixels/inch.
  1707.    The PageSetup is normal
  1708.        no enlargement/reduction
  1709.        no precision bit map 
  1710.        etc.
  1711.  
  1712. Each picture is the result of drawing a line of size #@(1 1)
  1713. from #@(0 0) to #@(100 100),coinciding with two corners of
  1714. the picture rectangle.
  1715.  
  1716. When the first picture is printed, the lines are normal size.
  1717. When the second picture is printed, the lines are hairline 1/4 thickness.
  1718.  
  1719.                     ; use quickdraw routines
  1720. (let (that
  1721.       new-picture)
  1722.   (eval-when (eval load compile)
  1723.     (require :quickdraw))
  1724.   (setq that (make-instance 'window))
  1725.   (window-select that)
  1726.   (set-view-size that 400 400)
  1727.   (loop for scaling in '(nil t)
  1728.         do(progn
  1729.             (with-focused-view that
  1730.               (start-picture that 0 0 100 100)
  1731.               (when scaling
  1732.                 (scale-line-width 1/4))
  1733.               (#_moveto 0 0)
  1734.               (#_lineto 100 50)
  1735.               (when scaling
  1736.                 (normal-line-width)))
  1737.             (setq new-picture (get-picture that))
  1738.             (draw-picture that new-picture 0 0 400 400)
  1739.             (picture-hardcopy new-picture)
  1740.             (kill-picture new-picture)))
  1741.   (window-close that))
  1742.  
  1743.  
  1744. Here's the end of the PostScript code corresponding to the first picture
  1745.  
  1746. T T 0 0 730 552 -31 -30 761 582 100 72 72 1 F F F F T T T F psu
  1747. (LARRY     Ecstatic; document: Untitled)jn
  1748. 0 mf
  1749. od
  1750. %%EndDocumentSetup
  1751. %%Page: ? 1
  1752. op
  1753. 0 0 730 552 fr
  1754. 0 0 xl
  1755. 1 1 pen
  1756. 0 0 gm
  1757. (nc 0 0 100 100 6 rc)kp
  1758. 50 100 lin
  1759. F T cp
  1760. %%Trailer
  1761. cd
  1762. end
  1763. %%Pages: 1 0
  1764. %%EOF
  1765.  
  1766. Here's the end of the PostScript code corresponding to the second picture
  1767.  
  1768. T T 0 0 730 552 -31 -30 761 582 100 72 72 1 F F F F T T T F psu
  1769. (LARRY     Ecstatic; document: Untitled)jn
  1770. 0 mf
  1771. od
  1772. %%EndDocumentSetup
  1773. %%Page: ? 1
  1774. op
  1775. 0 0 730 552 fr
  1776. 0 0 xl
  1777. 1 1 pen
  1778. 0 0 gm
  1779. (nc 0 0 0 0 6 rc)kp
  1780. 1 4 lw
  1781. (nc 0 0 100 100 6 rc)kp
  1782. 50 100 lin
  1783. 1 1 lw
  1784. F T cp
  1785. %%Trailer
  1786. cd
  1787. end
  1788. %%Pages: 1 0
  1789. %%EOF
  1790.  
  1791. |#
  1792. ;;; end of file